package com.ruoyi.report.service.Impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.parser.Feature;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.utils.DBUtil;
import com.ruoyi.report.domain.ReportDataSource;
import com.ruoyi.report.domain.ReportDataset;
import com.ruoyi.report.domain.ReportWorkbookConfig;
import com.ruoyi.report.domain.ReportWorkbookData;
import com.ruoyi.report.domain.dto.PerViewDataDto;
import com.ruoyi.report.mapper.ReportDataMapper;
import com.ruoyi.report.mapper.ReportDataSourceMapper;
import com.ruoyi.report.mapper.ReportDatasetMapper;
import com.ruoyi.report.mapper.ReportWorkbookDataMapper;
import com.ruoyi.report.service.IReportPerDataService;

import com.ruoyi.system.mapper.SysDictDataMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.sql.SQLException;
import java.util.*;

/**
 * @version v1.0
 * @ProjectName: report
 * @ClassName: ReportPerDataServiceImpl
 * @Description: 预览数据serviceImpl
 * @Author: sunyan
 * @Date: 2022/3/15 9:55
 */
@Service
public class ReportPerDataServiceImpl implements IReportPerDataService {

    @Autowired
    ReportWorkbookDataMapper reportWorkbookDataMapper;

    @Autowired
    ReportDataMapper reportDataMapper;

    @Autowired
    ReportDatasetMapper reportDatasetMapper;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    SysDictDataMapper sysDictDataMapper;

    @Autowired
    ReportDataSourceMapper reportDataSourceMapper;

    private static final String SqlType = "0";//sql类型
    private static final String ApiType = "1";//Api类型
    private static final String JsonType = "2";//Json类型

    //搜索框类型
    private static final String Input = "_IP";//输入框
    private static final String DropDownRadio = "_DR";//下拉单选
    private static final String DropDownMultSelect = "_MS";//下拉多选
    private static final String RangeQuery = "_RQ";//范围选择
    private static final String RangeQueryEnd = "_RE";//范围选择结束的值
    private static final String LikeSelect = "_LS";//模糊查询
    private static final String DropDownTree = "_DT";//下拉树

    @Override
    public Map<String,String> selectPerData(PerViewDataDto perViewDataDto) {
        Map<String, String> retMap = new HashMap<>();
        ReportWorkbookConfig reportWorkbookConfig = reportDataMapper.selectReportById(perViewDataDto.getReportId());
        ReportWorkbookData reportWorkbookData = reportWorkbookDataMapper.selectReportWorkbookDataById(perViewDataDto.getReportId(),perViewDataDto.getSheetIndex());
        //不包含数据集
        if(reportWorkbookConfig.getDatasetId() == null || reportWorkbookConfig.getDatasetId() == ""){
            JSONObject sheetDataJO = JSON.parseObject(reportWorkbookData.getSheetData());
            JSONObject config = (JSONObject) sheetDataJO.get("config");
            sheetDataJO.put("config",setAuthority(config));//表格保护
            retMap.put("sheetdata",sheetDataJO.toJSONString());
            retMap.put("datasetTable",null);
            return retMap;
        }else{
            Map<String,String> blankMap = new HashMap<>();
            //包含数据集
            //数据库是存储的datasetId是中间用”.“拼接的字符串 根据"."分隔为数组
            String[] dasetId = reportWorkbookConfig.getDatasetId().split("\\.");//以逗号分割 "\\." .默认是正则 \\转义
            //数组转化为List<long>
            List<Long> dasetIdList = new ArrayList<>();
            for(String s : dasetId){
                dasetIdList.add(Long.parseLong(s));
            }
            List<ReportDataset> datasetList = reportDatasetMapper.selectReportDatasetByIdList(dasetIdList);
            //获取数据
            JSONObject data = getDatasetData(datasetList,perViewDataDto);
            //获取字典
            JSONObject dict = getDict(datasetList);
            //转化成需要的格式把总数去掉
            JSONObject datasetMap = new JSONObject();
            for(String key : data.keySet()){
               JSONObject codedata = (JSONObject) JSON.toJSON(data.get(key));
               datasetMap.put(key,codedata.get("data"));
            }
            //根据查询参数处理数据
            if(perViewDataDto.getQueryParam() != null){
                datasetMap = filterDatasetMap(datasetMap,perViewDataDto.getQueryParam());
            }
            //sheet页数据
            JSONObject sheetDataJO = JSON.parseObject(reportWorkbookData.getSheetData());
            //data.celldata
            JSONArray celldata = (JSONArray) sheetDataJO.get("celldata");
            //data.config
            JSONObject config = (JSONObject) sheetDataJO.get("config");
            JSONArray retCelldata = new JSONArray();
            retCelldata.addAll(celldata);
            //循环celldata数组判断是否为动态数据
            for(Object o : celldata){
                //数据celldata[i]
                //{"r":3,"c":1,"v":{"ct":{"t":"g","fa":"General"},"v":"姓名","m":"姓名"}}
                JSONObject celldataIJO = (JSONObject) JSON.toJSON(o);
                //数据celldata[i].v
                //"v":{"ct":{"t":"g","fa":"General"},"v":"姓名","m":"姓名"}
                JSONObject celldataIVJO = (JSONObject) JSON.toJSON(celldataIJO.get("v"));
                String dynamicStr = celldataIVJO.getString("d");
                //数据celldata[i].v.v
                if(!(celldataIVJO.get("v") instanceof String)){
                    continue;
                }
                String str = (String) celldataIVJO.get("v");
                if(str == null){
                    continue;
                }
                //判断是不是动态数据$(*)
                if("dynamic".equals(dynamicStr)){
                    //把该格的表达式数据移除
                    retCelldata.remove(o);
                    int r = celldataIJO.getInteger("r");//行坐标
                    int c = celldataIJO.getInteger("c");//列坐标
                    int startr = r;//记录初始r行坐标
                    int startc = c;//记录初始c列坐标
                    //把外围的$()去掉
                    String param = str.substring(2,str.length()-1);
                    String[] strList = param.split("\\.");
                    //获取补全空白行单元格
                    if(JSONObject.parseObject(celldataIJO.get("v").toString()).get("blank") != null && JSONObject.parseObject(celldataIJO.get("v").toString()).getBoolean("blank")){
                        int blankTimes = JSONObject.parseObject(celldataIJO.get("v").toString()).getInteger("blankTimes");//补全行倍数
                        //在map中存放key为数据集编号，值为坐标和倍数
                        blankMap.put(strList[0],r+","+c+","+blankTimes);
                    }
                    //数据为空
                    if(datasetMap.get(strList[0]) == null){
                        break;
                    }else if(datasetMap.get(strList[0]) instanceof ArrayList || datasetMap.get(strList[0]) instanceof JSONArray){
                        JSONArray jsonArray = JSON.parseArray(JSON.toJSONString(datasetMap.get(strList[0])));
                        //数据类型为集合时 根据编码获取要动态添加的数据列表
                        for(Object arrayOb : jsonArray){
                            JSONObject jsob = (JSONObject) JSON.toJSON(arrayOb);
                            //翻译
                            Object v = transDict(jsob,strList[strList.length-1], (JSONObject) JSON.toJSON(dict.get(strList[0])),reportWorkbookConfig.getCreateBy());
                            celldataIVJO.put("v",v);
                            celldataIVJO.put("m",v);
                            JSONObject celldataIVJOPut = new JSONObject();
                            celldataIVJOPut.putAll(celldataIVJO);
                            celldataIJO.put("v",celldataIVJOPut);
                            celldataIJO.put("r",r);
                            celldataIJO.put("c",c);
                            if("row".equals(strList[1])){
                                //横向
                                //更改拼接数据的列宽
                                config = setColumnHeight(config,startc,c);
                                //修改边框的范围
                                config = setBorder(config,startr,startc,c,"column");
                                c++;
                            }else{
                                //纵向
                                //更改拼接的数据的行高和动态数据单元格一致
                                config = setRowHeight(config,startr,r);
                                //修改边框的范围
                                config = setBorder(config,startr,startc,r,"row");
                                r++;
                            }
                            JSONObject celldataIJOPut = new JSONObject();
                            celldataIJOPut.putAll(celldataIJO);
                            retCelldata.add(celldataIJOPut);
                        }
                    }else{
                        JSONObject jsob = (JSONObject)JSON.toJSON(datasetMap.get(strList[0]));
                        //翻译
                        Object v = transDict(jsob,strList[strList.length-1], (JSONObject) JSON.toJSON(dict.get(strList[0])),reportWorkbookConfig.getCreateBy());
                        celldataIVJO.put("v",v);
                        celldataIVJO.put("m",v);
                        JSONObject celldataIVJOPut = new JSONObject();
                        celldataIVJOPut.putAll(celldataIVJO);
                        celldataIJO.put("v",celldataIVJOPut);
                        celldataIJO.put("r",r);
                        celldataIJO.put("c",c);
                        JSONObject celldataIJOPut = new JSONObject();
                        celldataIJOPut.putAll(celldataIJO);
                        retCelldata.add(celldataIJOPut);
                    }

                }
            }

            //判断如果横纵坐标在边框行列范围之内，计算边框行数，用倍数除以行数的余数作为需要补充的行数
            //修改边框的行数范围
            //每个数据集只取一个补充行设置
            //如果配置中含有边框
            if(config.get("borderInfo") != null){

                JSONArray borderArray = config.getJSONArray("borderInfo");

                //遍历边框对象数组
                for (int i = 0; i < borderArray.size(); i++) {

                    //获取边框范围对象
                    Object borderObj = borderArray.get(i);

                    JSONObject borObj = JSONObject.parseObject(borderObj.toString());
                    JSONObject rangeObj = borObj.getJSONArray("range").getJSONObject(0);

                    //遍历补全行倍数map集合判断横纵坐标是否在边框范围之内
                    for (String key : blankMap.keySet()) {

                        String[] coordinate = blankMap.get(key).split(",");
                        int r = Integer.parseInt(coordinate[0]);
                        int c = Integer.parseInt(coordinate[1]);

                        //如果补全行倍数字段横纵坐标在边框范围内则按倍数修改边框范围
                        if(c>= rangeObj.getJSONArray("column").getInteger(0) && c <= rangeObj.getJSONArray("column").getInteger(1) &&
                                r >= rangeObj.getJSONArray("row").getInteger(0) && r<= rangeObj.getJSONArray("row").getInteger(1)){

                            //数据集大小即边框行数
                            int dataSize = rangeObj.getJSONArray("row").getInteger(1) - rangeObj.getJSONArray("row").getInteger(0) + 1;
                            //行倍数
                            int blankTimes =  Integer.parseInt(coordinate[2]);
                            //需补全行数
                            int completion = blankTimes % dataSize;
                            //如果设置补全行倍数小于数据集大小则将补全行倍数翻倍重新计算
                            int n =1;
                            while(completion == blankTimes){
                                n++;
                                completion = (n * blankTimes) % dataSize;
                            }
                            //修改边框范围
                            JSONArray rowArray = rangeObj.getJSONArray("row");
                            rowArray.set(1,rangeObj.getJSONArray("row").getInteger(1) + completion);
                        }
                    }
                    //重新设置边框对象
                    borderObj = borObj;
                    borderArray.set(i,borderObj);
                }

            }
            sheetDataJO.put("celldata",retCelldata);
            sheetDataJO.put("config",setAuthority(config));//表格保护
            retMap.put("sheetdata",sheetDataJO.toJSONString());//表格数据

            return retMap;
        }
    }

    @Override
    public Map<String, String> getQuery(PerViewDataDto perViewDataDto) {
        if(perViewDataDto.getPage() == null){
            perViewDataDto.setPage(new JSONObject());
        }
        ReportWorkbookConfig reportWorkbookConfig = reportDataMapper.selectReportById(perViewDataDto.getReportId());
        //数据库是存储的datasetId是中间用”.“拼接的字符串 根据"."分隔为数组
        if(reportWorkbookConfig.getDatasetId() == null){
            return null;
        }
        String[] dasetId = reportWorkbookConfig.getDatasetId().split("\\.");//以逗号分割 "\\." .默认是正则 \\转义
        //数组转化为List<long>
        List<Long> dasetIdList = new ArrayList<>();
        for(String s : dasetId){
            dasetIdList.add(Long.parseLong(s));
        }
        List<ReportDataset> datasetList = reportDatasetMapper.selectReportDatasetByIdList(dasetIdList);
        //获取数据
        JSONObject data = getDatasetData(datasetList,perViewDataDto);
        //转化成需要的格式把总数去掉
        JSONObject datasetMap = new JSONObject();
        JSONObject countMap = new JSONObject();
        for(String key : data.keySet()){
            JSONObject codedata = (JSONObject) JSON.toJSON(data.get(key));
            datasetMap.put(key,codedata.get("data"));
            countMap.put(key,codedata.get("count") == null ? 1 :codedata.get("count"));
        }
        List<JSONObject> datasetQueryData = getQueryData(datasetList,datasetMap);
        Map<String,String> retMap = new HashMap<>();
        retMap.put("datasetTable",JSON.toJSONString(datasetQueryData));//查询栏的数据
        retMap.put("count",JSON.toJSONString(countMap));
        return retMap;
    }

    /** 拼接返回的reportWookBookConfig的ReportData中data数据
     *  现在返回的是字符串 返回reportWorkbookConfig的该方法暂时没用
     * */
    private ReportWorkbookConfig concatReportData(ReportWorkbookConfig reportWorkbookConfig , String string){
        JSONObject js = JSON.parseObject(reportWorkbookConfig.getReportData());
        List<String> list = new ArrayList<>();
        //data的JSON字符串
        list.add(string);
        js.put("data", list);
        String s = JSON.toJSONString(js);
        reportWorkbookConfig.setReportData(s);
        return reportWorkbookConfig;
    }

    /**
     * datasetList 数据集列表
     * return map key为数据集编码 value为返回的JsonObject
     **/
    private JSONObject getDatasetData(List<ReportDataset> datasetList,PerViewDataDto perViewDataDto){
        JSONObject map = new JSONObject();//数据集编码：数据集数据
        //遍历数据集
        for (ReportDataset reportDataset: datasetList){
            if(SqlType.equals(reportDataset.getSqlApiType())){
                Object sqlDatasetData = null;
                if("1".equals(reportDataset.getIsPage())){
                    JSONObject pageobject = (JSONObject)JSONObject.toJSON(perViewDataDto.getPage().get(reportDataset.getDatasetCode()));
                    int pageSize = pageobject == null ? 10 : pageobject.getInteger("pageSize");
                    int pageNum = pageobject == null ? 0 : pageobject.getInteger("pageNum") - 1;
                    System.out.println(pageSize + pageNum);
                    sqlDatasetData = getSqlDatasetData(reportDataset.getDataSourceId(),reportDataset.getSqlApiString(),pageNum,pageSize);
                }else {
                    sqlDatasetData = getSqlDatasetData(reportDataset.getDataSourceId(),reportDataset.getSqlApiString(),null,null);
                }
                map.put(reportDataset.getDatasetCode(),sqlDatasetData);
            }else if(ApiType.equals(reportDataset.getSqlApiType()) ){
                JSONObject jsonObject;
                //参数是否为null
                if (null != JSON.parseObject(reportDataset.getRequestQuery())){
                    jsonObject = JSON.parseObject(reportDataset.getRequestQuery());
                }else{
                    //参数为null
                    jsonObject = new JSONObject();
                }
                if("1".equals(reportDataset.getIsPage())){
                    JSONObject pageobject = (JSONObject)JSONObject.toJSON(perViewDataDto.getPage().get(reportDataset.getDatasetCode()));
                    jsonObject.put("pageSize",pageobject == null ? 10 : pageobject.getInteger("pageSize"));
                    jsonObject.put("pageNum",pageobject == null ? 0 : pageobject.getInteger("pageNum") - 1);
                }
                Object  apiDataString =  getApiDatasetData(reportDataset.getRequestType(),
                        reportDataset.getSqlApiString(),
                        jsonObject);
                map.put(reportDataset.getDatasetCode(),apiDataString);
            }else if (JsonType.equals(reportDataset.getSqlApiType())){
                ArrayList<LinkedHashMap> linkedHashMaps = new ArrayList<>();
                String dataString = reportDataset.getJsonData();
                JSONObject jsonData =JSON.parseObject(dataString);
                //JSONObject jsonArr = (JSONObject) jsonData.getJSONArray("data").get(0);
                JSONArray jsonArray = jsonData.getJSONArray("data");
                for (int i = 0; i < jsonArray.size(); i++){
                    LinkedHashMap<String, String> param =  JSON.parseObject(jsonArray.getJSONObject(i).toJSONString(),LinkedHashMap.class, Feature.OrderedField);
                    linkedHashMaps.add(param);
                }
                //Map<String, String> params =  JSON.parseObject(jsonArr.toJSONString(),LinkedHashMap.class, Feature.OrderedField);
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("data",linkedHashMaps);
                map.put(reportDataset.getDatasetCode(),jsonObject);
            }
        }

        return map;
    }

    /**
     * 获取api数据的方法
     * method 请求方法
     * url 请求地址
     * query 请求参数
     **/
    private Object getApiDatasetData(String method, String url, JSONObject query) {

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        //请求方法体
        HttpMethod httpMethod = HttpMethod.GET;
        HttpEntity<JSONObject> entity = new HttpEntity<>(query, headers);
        if ("GET".equals(method)){
            if (query != null){
                url = url + "?";
                for(String key : query.keySet()){
                    url = url + key + "=" + String.valueOf(query.get(key)) + "&";
                }
                url = StringUtils.substring(url,0,-1);
            }
            try {
                ResponseEntity<JSONObject> responseData = restTemplate.exchange(url, httpMethod, null, JSONObject.class);
                if (responseData.getBody() != null) {
                    JSONObject jsonObject = responseData.getBody();
                    if(jsonObject.get("data") != null){
                        return jsonObject;
                    }else{
                        throw new Exception("数据返回格式有误");
                    }
                }else{
                    throw new Exception("请检查接口地址和参数是否正确");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        else if ("POST".equals(method)) {
            httpMethod = HttpMethod.POST;
            try {
                ResponseEntity<JSONObject> responseData = restTemplate.exchange(url, httpMethod, entity, JSONObject.class);
                if (responseData.getBody() != null) {
                    JSONObject jsonObject = responseData.getBody();
                    if(jsonObject.get("data") != null){
                        return jsonObject;
                    }else{
                        throw new Exception("数据返回格式有误");
                    }
                } else {
                    throw new Exception("请检查接口地址和参数是否正确");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
    /**
     * 获取sql数据的方法
     * method 请求方法
     * url 请求地址
     * query 请求参数
     **/
    private Object getSqlDatasetData(Long dataSourceId, String sql,Integer pageNum, Integer pageSize) {
        ReportDataSource reportDataSource = reportDataSourceMapper.selectReportDataSourceById(dataSourceId);
        String drive = null;
        if ("mysql".equals(reportDataSource.getDatabaseType())) {
            drive = "com.mysql.cj.jdbc.Driver";
        }
        String url = "jdbc:mysql://" +reportDataSource.getIpAddress()+":" + reportDataSource.getPort() + "/" +
                reportDataSource.getBaseName() + "?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8";
        JSONArray arr = null;
        int count = 0;
        try {
            if(!(null == pageNum || null == pageSize)){
                sql = sql + " limit " + pageNum*pageSize+","+pageSize;
            }
            System.out.println(sql);
            arr = DBUtil.execute(drive, url, reportDataSource.getUsername(), reportDataSource.getPassword(), sql);
            count = DBUtil.getcount(drive, url, reportDataSource.getUsername(), reportDataSource.getPassword(), sql);
        } catch (SQLException e) {
            e.printStackTrace();
            return AjaxResult.error("操作错误");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return AjaxResult.error("操作错误");
        }
        JSONObject ret = new JSONObject();
        ret.put("data",arr);
        ret.put("count",count);
        return ret;
    }


    /**
     * 根据查询参数过滤数据
     * datasetMap 数据集数据
     * queryParam 查询参数JSONString
     **/
    private  JSONObject filterDatasetMap(JSONObject datasetMap,String queryParam){
        Set<String> codeSet = datasetMap.keySet();
        JSONObject queryData = JSON.parseObject(queryParam);
        //遍历数据集编码
        for(String code : codeSet){
            //该编码对应的数据
           JSONObject js = (JSONObject) JSON.toJSON(queryData.get(code));
           //数据为空说明没有查询参数  略过该循环
            if(js == null){
                continue;
            }
           if(js.isEmpty()){
               continue;
           }
           Set<String> keySet = js.keySet();
           for (String key : keySet) {
               //复制该编码数据集数据 list
               JSONArray list = new JSONArray();
               JSONArray jsonArray = JSON.parseArray(JSON.toJSONString(datasetMap.get(code)));
               list.addAll(jsonArray);
               //遍历数据集数据挨个比较是否符合条件
               for (Object object : jsonArray) {
                   JSONObject json = (JSONObject) JSON.toJSON(object);
                   //判断搜索框类型
                   switch (StringUtils.substring(key,-3)){
                       case Input:
                           //输入框 不符合条件删除
                           if (!js.get(key).equals(json.get(StringUtils.substring(key,0,-3)))) {
                               list.remove(object);
                           }
                           break;
                       case DropDownRadio:
                           //下拉单选 不符合条件删除
                           if (!js.get(key).equals(json.get(StringUtils.substring(key,0,-3)))) {
                               list.remove(object);
                           }
                           break;
                       case DropDownMultSelect:
                           //多选判断数据在不在数组中 不在则删除
                           if(!((JSONArray) js.get(key)).contains(json.get(StringUtils.substring(key,0,-3)))){
                               list.remove(object);
                           }
                           break;
                       case RangeQuery:
                           String value = String.valueOf(json.get(StringUtils.substring(key,0,-3)));
                           String begin = String.valueOf(js.get(key));
                           String valueKey = StringUtils.substring(key,0,-3) + RangeQueryEnd;
                           String end = String.valueOf(js.get(valueKey));
                           if(!(compareString(begin,value) <= 0 && compareString(end,value) >= 0)){
                               list.remove(object);
                           }
                           break;
                       case LikeSelect:
                           //模糊匹配
                           if(!StringUtils.contains((String)json.get(StringUtils.substring(key,0,-3)),(String) js.get(key))){
                               list.remove(object);
                           }
                           break;
                       case DropDownTree:
                           System.out.println(DropDownTree);
                           break;
                   }
               }
               //更新数据集
               datasetMap.put(code,list);
           }
        }
        return datasetMap;
    }

    /**
     * 设置工作表保护config.authority
     * */
    private JSONObject setAuthority(JSONObject config){
        JSONObject authority = new JSONObject();
        authority.put("selectLockedCells",1); //选定锁定单元格
        authority.put("selectunLockedCells",1); //选定解除锁定的单元格
        authority.put("formatCells",1); //设置单元格格式
        authority.put("formatColumns",1); //设置列格式
        authority.put("formatRows",1); //设置行格式
        authority.put("insertColumns",1); //插入列
        authority.put("insertRows",1); //插入行
        authority.put("insertHyperlinks",1); //插入超链接
        authority.put("deleteColumns",1); //删除列
        authority.put("deleteRows",1); //删除行
        authority.put("sort",1); //排序
        authority.put("filter",1); //使用自动筛选
        authority.put("usePivotTablereports",1); //使用数据透视表和报表
        authority.put("editObjects",1); //编辑对象
        authority.put("editScenarios",1); //编辑方案
        authority.put("sheet",1); //如果为1或true，则该工作表受到保护；如果为0或false，则该工作表不受保护。
        authority.put("hintText","预览不允许修改"); //弹窗提示的文字
        authority.put("algorithmName","None"); //加密方案：MD2,MD4,MD5,RIPEMD-128,RIPEMD-160,SHA-1,SHA-256,SHA-384,SHA-512,WHIRLPOOL
        authority.put("algoritsaltValuehmName","454qqweqwe"); //加密方案：MD2,MD4,MD5,RIPEMD-128,RIPEMD-160,SHA-1,SHA-256,SHA-384,SHA-512,WHIRLPOOL
        config.put("authority",authority);
        return config;
    }

    /** 判断动态数据是否有边框  有边框动态拼接
     * config data.config对象
     * start 动态数据单元格所在的行数
     * endr 动态增加之后的行数
     * c初始的列数
     **/
    private JSONObject setBorder(JSONObject config,int startr,int startc, int value, String type){

        JSONArray configBorder = (JSONArray)config.get("borderInfo");

        Boolean isHaveBorder = false;
        JSONObject removeborder = new JSONObject();
        if(config.containsKey("borderInfo")){
            for (Object cb : configBorder){
                //获取config.borderInfo[i].range[0]下的边框行纵范围
                JSONObject jsbean = (JSONObject) JSON.toJSON(cb);
                JSONArray jsrange = (JSONArray) jsbean.get("range");
                if(jsrange == null || jsrange.size() == 0){
                    continue;
                }
                JSONObject jsrange0 = (JSONObject) jsrange.get(0);
                JSONArray jsc = (JSONArray) jsrange0.get("column");
                JSONArray jsr = (JSONArray) jsrange0.get("row");
                //判断该动态数据在不在边框内 在的话需要更改边框范围
                if(startc >= jsc.getInteger(0) && startc <= jsc.getInteger(1) && startr >= jsr.getInteger(0) && startr <= jsr.getInteger(1)){
                    isHaveBorder = true;
                    //该动态数据所在的对象 需要被移除
                    removeborder = (JSONObject) JSON.toJSON(cb);
                }
            }
        }
        //修改边框的范围
        if(isHaveBorder){
            //移除原来的边框对象
            configBorder.remove(removeborder);
            JSONObject borderPut = new JSONObject();
            borderPut.putAll(removeborder);
            //修改config.borderInfo[i].range[0].row[1]为动态添加完数据后所占行数
            JSONArray jsrange = (JSONArray) borderPut.get("range");//config.borderInfo[i].range
            JSONObject jsrange0 = (JSONObject) jsrange.get(0);//config.borderInfo[i].range[0]
            JSONArray jsrow = (JSONArray) jsrange0.get(type);//config.borderInfo[i].range[0].row
            jsrow.remove(1);
            jsrow.add(1,value);
            configBorder.add(borderPut);
            config.put("borderInfo",configBorder);
        }
        return config;
    }

    /** 判断动态数据是否更改了行高  更改的话拼接的数据行高都需要更改
     * config data.config对象
     * start 动态数据单元格所在的行
     * nowr 循环中添加的行坐标
     **/
    private JSONObject setRowHeight(JSONObject config,int startr,int nowr){
        //是否改变行高
        Boolean isHaveRowConfig = false;
        int rowlen = 20;
        //data.config.rowlen
        if(config.containsKey("rowlen")){
            JSONObject configRowlen = (JSONObject) config.get("rowlen");
            //纵向排列单元格的congfig
            isHaveRowConfig = configRowlen.containsKey(String.valueOf(startr));
            rowlen = (int) configRowlen.get(String.valueOf(startr));
        }
        if(isHaveRowConfig){
            JSONObject configRowlen = (JSONObject) config.get("rowlen");
            configRowlen.put(String.valueOf(nowr),rowlen);
        }
        return config;
    }

    /** 判断动态数据是否更改了列宽  更改的话拼接的数据行高都需要更改
     * config data.config对象
     * starc 动态数据单元格所在的列
     * nowc 循环中添加的列坐标
     **/
    private JSONObject setColumnHeight(JSONObject config,int startc,int nowc){
        //是否改变行高
        Boolean isHaveColumnConfig = false;
        int columnlen = 20;
        //data.config.rowlen
        if(config.containsKey("columnlen")){
            JSONObject configColumnlen = (JSONObject) config.get("columnlen");
            //纵向排列单元格的congfig
            isHaveColumnConfig = configColumnlen.containsKey(String.valueOf(startc));
            columnlen = (int) configColumnlen.get(String.valueOf(startc));
        }
        if(isHaveColumnConfig){
            JSONObject configRowlen = (JSONObject) config.get("columnlen");
            configRowlen.put(String.valueOf(nowc),columnlen);
        }
        return config;
    }

    /** 获取查询栏所需的数据格式 如果没有返回null
     * datesetMap 获取到的数据集数据
     * datasetList 数据库存储的数据集相关配置
     **/
    private List<JSONObject> getQueryData(List<ReportDataset> datasetList,JSONObject datasetMap){
        List<JSONObject> retList = new ArrayList<>();
//        Boolean havequery = false;//是否有查询参数
        for(ReportDataset reportDataset : datasetList){
            JSONArray jsonArray = JSONArray.parseArray(reportDataset.getDatasetData());
            List<JSONObject> datasetTable = new ArrayList<>();
            //循环判断是否有isquery = 1
            for(Object o : jsonArray){
                JSONObject jsonObject = (JSONObject) JSON.toJSON(o);
                if("1".equals(jsonObject.get("isQuery"))){
//                    havequery = true;//有查询参数
                    JSONObject datasetTableMap = new JSONObject();
                    datasetTableMap.put("name", jsonObject.get("name"));
                    datasetTableMap.put("label", jsonObject.get("label"));
                    datasetTableMap.put("sort", jsonObject.getInteger("sort"));
                    datasetTableMap.put("queryType", jsonObject.get("queryType"));
                    //如果查询类型是下拉选择获取下拉数组set
                    if("dropDownRadio".equals(jsonObject.get("queryType"))||
                            "dropDownMultSelect".equals(jsonObject.get("queryType"))||
                            "rangeQuery".equals(jsonObject.get("queryType"))){
                       JSONArray datasetData = JSON.parseArray(JSON.toJSONString(datasetMap.get(reportDataset.getDatasetCode())));
                       Set<Object> set = new HashSet<>();
                       for (Object o1 : datasetData){
                           JSONObject object = (JSONObject) JSON.toJSON(o1);
                           set.add(object.get(jsonObject.get("name")));
                       }
                        datasetTableMap.put("options",set);
                    }else{
                        datasetTableMap.put("options",null);
                    }
                    datasetTableMap.put("type", jsonObject.get("type"));
                    datasetTable.add(datasetTableMap);
                }
            }
            JSONObject map = new JSONObject();
            map.put("dsCode",reportDataset.getDatasetCode());
            map.put("dsName",reportDataset.getDatasetName());
            map.put("tableData",datasetTable);
            retList.add(map);
        }
//        return havequery ?  retList : null;
        return retList;
    }

    /**
     *  比较字符串类型的数字大小
     *  s1 > s2 返回int > 0
     *  s1 = s2 int = 0
     *  s1 < s2 int <0
     *  未考虑浮点数
     * */
    private int compareString(String s1,String s2){
        if(s1.length() > s2.length()){
            return 1;
        }else if(s1.length() == s2.length()){
            return s1.compareTo((s2));
        }else {
            return -1;
        }
    }

/**
 * 获取字典
 * */
    private JSONObject getDict(List<ReportDataset> list){
        JSONObject ret = new JSONObject();
        JSONObject dict = new JSONObject();
        for(ReportDataset reportDataset : list){
           JSONArray datasetData = JSONArray.parseArray(reportDataset.getDatasetData());
           for (Object o : datasetData){
               JSONObject js = (JSONObject) JSON.toJSON(o);
               if(js.get("dict") != null){
                   dict.put((String)js.get("name"), js.get("dict"));
               }
           }
           ret.put(reportDataset.getDatasetCode(),dict);
        }
        return ret;
    }

    /**
     * jsonObject
     * str
     * dict
     * createBy
     */
    private Object transDict(JSONObject jsonObject,String str,JSONObject dict,String createBy){
        if(dict!= null && dict.get(str) != null){
            List<SysDictData> list = sysDictDataMapper.selectDictLabelByCreateAndDictType((String) dict.get(str),createBy);
            for(SysDictData sysDictData : list){
                if(jsonObject.get(str).equals(sysDictData.getDictValue())){
                    return sysDictData.getDictLabel();
                }
            }
        }
        return jsonObject.get(str);
    }
}
